package org.abstractmeta.commandify.core.command.reflectify;

import org.abstractmeta.commandify.core.command.AbstractMethodCommand;
import org.abstractmeta.reflectify.MethodInvoker;
import org.abstractmeta.reflectify.Reflectify;

/**
 * Reflectify based method command
 */
public class ReflectifyMethodCommand<T> extends AbstractMethodCommand<T> {

    private final MethodInvoker<T, Object> methodInvoker;

    public ReflectifyMethodCommand(Reflectify<T> reflectify, String source) {
        this(reflectify, source, ZERO_ARGUMENT_TYPES);
    }

    public ReflectifyMethodCommand(Reflectify<T> reflectify, String source, Class[] types, Object... values) {
        super(source, types, values);
        this.methodInvoker = reflectify.getMethodInvoker(Object.class, source, types);
    }

    @Override
    public void execute(T instance) {
        Object [] values = getValues();
        for (int i = 0; i < values.length; i++) {
            Object clonedValue = getCommandValue(values[i]);
            methodInvoker.getParameterSetter(i).set(clonedValue);
        }
        methodInvoker.invoke(instance);
    }

}
